package cn.tedu.ivos.base.security;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.file.ConfigurationSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

//认证的配置类
@Slf4j
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private CustomAuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private CustomAuthenticationProvider authenticationProvider;

    @Autowired
    private CustomAccessDeniedHandler accessDeniedHandler;
    @Autowired
    private CustomAuthenticationEntryPoint authenticationEntryPoint;
    //HttpSecurity用于配置认证相关的信息
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()  //禁用跨站请求保护
                   .httpBasic() //配置http基本认证
                   .and().authorizeRequests() //配置请求授权，默认禁用所有请求
                   .antMatchers(
                        "/doc.html",
                           "/**/*.js",
                           "/**/*.css",
                           "/swagger-resources",
                           "/v2/api-docs",
                           "/**"
                   ).permitAll() //配置自动放行的资源,指定资源
                   .anyRequest().authenticated() //对其他所有请求要求用户必须要认证通过
                   .and().formLogin() //表单登录，默认拦截登录请求地址 /login
                   .successHandler(authenticationSuccessHandler)  //设置认证成功处理器，处理过程繁琐需要用类封装
                   .failureHandler(authenticationFailureHandler) //设置认证失败处理器，处理过程繁琐需要用类封装
                   .permitAll()
                   .and().exceptionHandling() //当用户尝试访问时，没有权限如何处理
                   .authenticationEntryPoint(authenticationEntryPoint) //未登录
                   .accessDeniedHandler(accessDeniedHandler) //权限不足
                   .and().cors() //配置跨域的请求
                   .configurationSource(corsConfigurationSource()) //设置跨域配置源
        ;//允许所有用户进行登录尝试
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //把认证的对象添加进来
        auth.authenticationProvider(authenticationProvider);
    }

    //设置跨域配置源
    private CorsConfigurationSource corsConfigurationSource(){
        //创建一个新的Cors的对象
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //允许请求携带凭证 cookie
        corsConfiguration.setAllowCredentials(true);
        //允许所有请求头
        corsConfiguration.addExposedHeader("*");
        //允许所有的请求方法类型
        corsConfiguration.addAllowedMethod("*");
        //允许响应头被客户端访问
        corsConfiguration.addExposedHeader("*");
        //允许来自任何请求源的请求
        corsConfiguration.addAllowedOriginPattern("*");
        //创建一个基于URL的CORS的配置源
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //将corsConfiguration对象添加到source对象中,将以上配置应用于所有路径
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
}
